package com.kucan.recyclecard.net;

import android.content.Context;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.kucan.recyclecard.constants.Constant;
import com.kucan.recyclecard.eventbus.EventCenter;
import com.kucan.recyclecard.eventbus.EventConstants;
import com.kucan.recyclecard.utils.DataUtils;
import com.kucan.recyclecard.utils.LogUtil;
import com.kucan.recyclecard.utils.NetCheckUtil;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


/**
 * Created by Administrator on 2017/5/2 0002.
 */

public class OkHttpEngine {
    private OkHttpClient mOkHttpClient;//懒加载

    private final static String JSON = "application/json; charset=utf-8";
    private static OkHttpEngine mInstance = null;
    private Gson mGson;
    private Context mContext;

    public static OkHttpEngine getInstance(Context context) {
        if (mInstance == null) {
            synchronized (OkHttpEngine.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpEngine(context);
                }
            }
        }
        return mInstance;
    }

    /**
     * http配置
     *
     * @param context
     */
    private OkHttpEngine(Context context) {
        mContext = context;
        mOkHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(Constant.TIME_OUT, TimeUnit.MILLISECONDS)
                .readTimeout(Constant.TIME_OUT, TimeUnit.MILLISECONDS).build();
//        mOkHttpClient = setCertificate();
        mGson = new Gson();
    }

    /**
     * https配置
     *
     * @return
     */
    private OkHttpClient setCertificate() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .addInterceptor(chain -> {
                    long startTime = System.currentTimeMillis();
                    okhttp3.Response response = chain.proceed(chain.request());
                    long endTime = System.currentTimeMillis();
                    long duration = endTime - startTime;
                    String requestMethod = chain.request().method();
                    String requestUrl = chain.request().url().toString();

                    // 打印请求时间和URL
                    LogUtil.d("dangzt", requestMethod + " " + requestUrl + " took " + duration + " ms");

                    return response;
                })
                .connectTimeout(Constant.TIME_OUT, TimeUnit.MILLISECONDS)
                .readTimeout(Constant.TIME_OUT, TimeUnit.MILLISECONDS);
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            String certificateAlias = Integer.toString(0);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(mContext.getAssets().open("fenghuang.crt")));//拷贝好的证书
            SSLContext sslContext = SSLContext.getInstance("TLS");
            final TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init
                    (
                            null,
                            trustManagerFactory.getTrustManagers(),
                            new SecureRandom()
                    );
            builder.sslSocketFactory(sslContext.getSocketFactory());
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return builder.build();
    }

    /**
     * post请求
     *
     * @param paramsMap 请求参数
     * @param method    url拼接
     * @param callBack  回调
     */
    public void postAsync(Map<String, Object> paramsMap, String method, final ApiCallBack<String> callBack) {
        if (!NetCheckUtil.isNetConnected(mContext)) {
            callBack.onFailure(Constant.NO_NETWORK, Constant.NO_NETWORK_MSG);
            return;
        }

//        设置固定参数
        paramsMap.put("platform", 9);

        //设置body
        JSONObject body = new JSONObject();
        try {
            if (null != paramsMap) {
                for (String key : paramsMap.keySet()) {
                    if (paramsMap.get(key) instanceof List) {
                        ArrayList mList = (ArrayList) paramsMap.get(key);
                        JSONArray array = new JSONArray();
                        for (Object m : mList) {
                            array.put(m);
                        }
                        body.put(key, array);
                    } else {
                        body.put(key, paramsMap.get(key));
                    }
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        RequestBody requestBody = RequestBody.create(MediaType.parse(JSON), body.toString());

        //设置header
        // 添加公共参数到header
        Headers.Builder headerBuild = new Headers.Builder();
        if (!TextUtils.isEmpty(DataUtils.getToken(mContext))) {
            headerBuild.add("token", DataUtils.getToken(mContext));
        }
        Headers headers = headerBuild.build();

        //设置url
        final String url = Constant.SERVER_URL + method;

        //设置request
        final Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .headers(headers)
                .build();
        LogUtil.d("url = " + url + " ====header = " + headers.toString());
        LogUtil.d("url = " + url + " ====json = " + body.toString());

        //发起请求
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callBack.onFailure(Constant.FAILED, Constant.TIME_OUT_EVENT_MSG);
            }

            @Override
            public void onResponse(Call call, Response response) {
                try {
                    String str = response.body().string();
                    LogUtil.d("url = " + url + "  = " + str);
                    JSONObject jsonObject = new JSONObject(str);
                    String code = "";
                    try {
                        code = jsonObject.getString("code");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    if (code == null || code.isEmpty()) {
                        callBack.onFailure(Constant.FAILED, Constant.TIME_OUT_EVENT_MSG);
                    } else if (code.equals("200")) {
                        callBack.onSuccess(str);
                    } else if (code.equals("403")) {
                        callBack.onFailure(code, jsonObject.getString("msg"));
                        //清除用户登录信息
//                        DataUtils.clearUserInfo(mContext);
                        //发送token过期事件
                        EventBus.getDefault().post(new EventCenter(EventConstants.EVENTCODE_TOKEN_ERRO));
                    } else {
                        callBack.onFailure(code, jsonObject.getString("msg"));
                    }
//                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.onFailure(Constant.FAILED, Constant.TIME_OUT_EVENT_MSG);
                }
            }
        });
    }


    public void getAsync(Map<String, Object> paramsMap, String method, final ApiCallBack<String> callBack) {
        if (!NetCheckUtil.isNetConnected(mContext)) {
            callBack.onFailure(Constant.NO_NETWORK, Constant.NO_NETWORK_MSG);
            return;
        }

        //设置url
        final String url = Constant.SERVER_URL + method;

//        设置固定参数
        paramsMap.put("platform", 9);

        String finalUrl = buildGetUrl(url, paramsMap); // 拼接URL参数[1,2](@ref)

        //设置header
        // 添加公共参数到header
        Headers.Builder headerBuild = new Headers.Builder();
        if (!TextUtils.isEmpty(DataUtils.getToken(mContext))) {
            headerBuild.add("token", DataUtils.getToken(mContext));
        }
        Headers headers = headerBuild.build();

        //设置request
        final Request request = new Request.Builder()
                .url(url)
                .get()
                .headers(headers)
                .build();
        LogUtil.d("url = " + url + " ====header = " + headers.toString());
        LogUtil.d("url = " + url + " ==== = " + finalUrl);

        //发起请求
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callBack.onFailure(Constant.FAILED, Constant.TIME_OUT_EVENT_MSG);
            }

            @Override
            public void onResponse(Call call, Response response) {
                try {
                    String str = response.body().string();
                    LogUtil.d("url = " + url + "  = " + str);
                    JSONObject jsonObject = new JSONObject(str);
                    String code = "";
                    try {
                        code = jsonObject.getString("code");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    if (code == null || code.isEmpty()) {
                        callBack.onFailure(Constant.FAILED, Constant.TIME_OUT_EVENT_MSG);
                    } else if (code.equals("200")) {
                        callBack.onSuccess(str);
                    } else if (code.equals("403")) {
                        callBack.onFailure(code, jsonObject.getString("msg"));
                        //清除用户登录信息
//                        DataUtils.clearUserInfo(mContext);
                        //发送token过期事件
                        EventBus.getDefault().post(new EventCenter(EventConstants.EVENTCODE_TOKEN_ERRO));
                    } else {
                        callBack.onFailure(code, jsonObject.getString("msg"));
                    }
//                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.onFailure(Constant.FAILED, Constant.TIME_OUT_EVENT_MSG);
                }
            }
        });
    }

    // 构建带参数的GET URL
    private static String buildGetUrl(String baseUrl, Map<String, Object> params) {
        StringBuilder urlBuilder = new StringBuilder(baseUrl);
        urlBuilder.append("?");

        for (Map.Entry<String, Object> entry : params.entrySet()) {
            urlBuilder.append(entry.getKey())
                    .append("=")
                    .append(entry.getValue())
                    .append("&");
        }

        // 删除末尾多余的 & 符号
        if (urlBuilder.charAt(urlBuilder.length() - 1) == '&') {
            urlBuilder.deleteCharAt(urlBuilder.length() - 1);
        }

        return urlBuilder.toString();
    }
}
